package com.wangwenjun.concurrency.chapter14.blockingqueue;

import org.junit.Test;

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @Package: com.wangwenjun.concurrency.chapter14.blockingqueue
 * @ClassName: UseBlockingQueue
 * @Author: lujieni
 * @Description: 1
 * @Date: 2021-03-10 16:07
 * @Version: 1.0
 *
 *  ArrayBlockingQueue
 *  1.有界
 *  2.先进先出
 *  3.线程安全
 *  4.提供put和take的阻塞api
 *
 */
public class UseArrayBlockingQueue {

    public static void main(String[] args) throws Exception {
        test04();
    }

    /**
     *
     * add方法超过队列容量会直接抛异常
     *
     */
    @Test
    public void testAdd(){
        Queue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.add(1));
        System.out.println(blockingQueue.add(2));
        System.out.println(blockingQueue.add(3));

        // IllegalStateException: Queue full 抛出异常
        blockingQueue.add(4);
    }

    /**
     * remove如果队列为空会抛异常,和add类似
     */
    @Test
    public void testRemove(){
        Queue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.add(1));
        System.out.println(blockingQueue.add(2));
        System.out.println(blockingQueue.add(3));

        blockingQueue.remove();
        blockingQueue.remove();
        blockingQueue.remove();
        blockingQueue.remove();

    }

    /**
     * offer方法超过队列容量会直接返回false,并不会抛异常
     */
    @Test
    public void testOffer(){
        Queue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.offer(4));
    }

    /**
     * poll队列为空会返回null, 不会抛异常
     */
    @Test
    public void testPoll(){
        Queue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
    }

    /**
     * put方法超过队列容量会直接阻塞
     */
    @Test
    public void testPut() throws InterruptedException {
        ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue(3);
        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.put(3);
        blockingQueue.put(4);
    }

    @Test
    public void testTake() throws InterruptedException {
        ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue(3);
        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.put(3);


        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();
    }


    /**
     * Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
     * Returns:
     * the head of this queue, or null if this queue is empty
     *
     * peek只看队首元素是啥但不移除元素,如果队列为空返回null
     */
    @Test
    public void testPeek(){
        Queue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
    }



    /**
     * @Description:抛出异常
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/10
     */
    private static void test011(){

        ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.element());//查看队首元素是啥,如果没有会抛出异常

        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());

        // java.util.NoSuchElementException 抛出异常
        System.out.println(blockingQueue.remove());

    }

    private static void test02(){
        ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        // false 不抛出异常
        // System.out.println(blockingQueue.offer(4));

        System.out.println(blockingQueue.peek());//队首元素是啥,不会抛出异常

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());//null 不抛出异常
    }

    /**
     * @Description: 等待,一直阻塞
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/10
     */
    private static void test03() throws InterruptedException{
        ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.put(3);

        // blockingQueue.put(4);一直阻塞

        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());// 没有这个元素,一直阻塞

    }

    /**
     * @Description: 超时退出
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/10
     */
    private static void test04() throws InterruptedException{
        ArrayBlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        //System.out.println(blockingQueue.offer(4, 2, TimeUnit.SECONDS));//等待2秒后如果还是满的就退出

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS));//等待2秒就退出


    }


}